/*
 * UMediaSinkArray.cpp
 *
 *  Created on: 2020年4月29日
 *      Author: chuanjiang.zh
 */

#include "UMediaSinkArray.h"

typedef std::deque< UMediaSink* >		MediaSinkDeque;

class UMediaSinkArrayPrivate
{
public:
	MediaSinkDeque::iterator find(UMediaSink* sink)
	{
		return std::find(m_sinks.begin(), m_sinks.end(), sink);
	}

	MediaSinkDeque	m_sinks;
	comn::CriticalSection m_cs;

	bool doExists(UMediaSink* sink)
	{
		MediaSinkDeque::iterator it = find(sink);
		return (it != m_sinks.end());
	}


};



UMediaSinkArray::UMediaSinkArray():
		m_pimp(new UMediaSinkArrayPrivate())
{
}

UMediaSinkArray::~UMediaSinkArray()
{
	removeSinks();

	delete m_pimp;
}

size_t UMediaSinkArray::size()
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	comn::AutoCritSec lock(m_pimp->m_cs);
	return m_sinks.size();
}

bool UMediaSinkArray::addSink(UMediaSink* pSink)
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	if (!pSink)
	{
		return false;
	}

	comn::AutoCritSec lock(m_pimp->m_cs);

	if (m_pimp->doExists(pSink))
	{
		return false;
	}

	m_sinks.push_back(pSink);
	return true;
}

bool UMediaSinkArray::removeSink(UMediaSink* pSink)
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	bool found = false;
	comn::AutoCritSec lock(m_pimp->m_cs);
	MediaSinkDeque::iterator it = m_pimp->find(pSink);
	if (it != m_sinks.end())
	{
		m_sinks.erase(it);
		found = true;
	}
	return found;
}

void UMediaSinkArray::removeSinks()
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	comn::AutoCritSec lock(m_pimp->m_cs);
	m_sinks.clear();
}

size_t UMediaSinkArray::getSinkCount()
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	comn::AutoCritSec lock(m_pimp->m_cs);
	return m_sinks.size();
}

bool UMediaSinkArray::exists(UMediaSink* sink)
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	comn::AutoCritSec lock(m_pimp->m_cs);
	MediaSinkDeque::iterator it = m_pimp->find(sink);
	return (it != m_sinks.end());
}

void UMediaSinkArray::fireMediaFormat(const UMediaFormat& fmt)
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	comn::AutoCritSec lock(m_pimp->m_cs);
	for (size_t i = 0; i < m_sinks.size(); ++ i)
	{
		m_sinks[i]->onMediaFormat(fmt);
	}
}

void UMediaSinkArray::fireMediaPacket(UMediaPacket& pkt)
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	comn::AutoCritSec lock(m_pimp->m_cs);
	for (size_t i = 0; i < m_sinks.size(); ++ i)
	{
		m_sinks[i]->onMediaPacket(pkt);
	}
}

void UMediaSinkArray::fireMediaEvent(int event)
{
	MediaSinkDeque& m_sinks = m_pimp->m_sinks;

	comn::AutoCritSec lock(m_pimp->m_cs);
	for (size_t i = 0; i < m_sinks.size(); ++ i)
	{
		m_sinks[i]->onMediaEvent(event);
	}
}

